import os, re
import shutil

base_path = '/'

def set_base_path(path:str) -> list[bool, str]:
    """Set the base path for all file operations."""
    try:
        global base_path
        base_path = path.replace('\\', '/')
    except Exception as Error:
        return [False, str(Error)]
    return [True, '']

def secure_path(path:str) -> str:
    """Secure the given path by checking if it is within the base path."""
    path = (os.path.normpath(path).replace('\\', '/') + ('/' if path.endswith('/') else '')).replace('//', '/')
    return path if path.startswith(base_path) else base_path

def intact_path(path:str) -> str:
    """Get the real absolute path of a given path."""
    return secure_path((base_path if not base_path.endswith('/') else base_path[:-1]) + path.replace('\\', '/'))

def real_path(path:str) -> str:
    """Translate a given path to an absolute path based on the base_path."""
    path = intact_path(path)
    path = (path[1:2] + ':' + (path[2:] if path[2:] else '/')).replace('/', '\\')
    return path if path != ':\\' else ''

def list_drive_letters() -> list[str]:
    """List all available drive letters."""
    return [x + '/' for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if os.path.exists(x + ':\\')]

def list_directory(directory:str) -> tuple[list[str], int, str]:
    """List all files in the given directory."""
    def natural_sort_list(List):
        return [int(text) if text.isdigit() else text.lower()
            for text in re.split(r'(\d+)', List)]
    directory = real_path(directory)
    try:
        if  not directory:
            return list_drive_letters(), 0, ''
        return [x + '/' for x in sorted(os.listdir(directory), key=natural_sort_list) if os.path.isdir (os.path.join(directory, x))] + \
               [x       for x in sorted(os.listdir(directory), key=natural_sort_list) if os.path.isfile(os.path.join(directory, x))] , 0, ''
    except FileNotFoundError:
        return [], 10, 'Directory not found'
    except PermissionError:
        return [], 20, 'Permission denied'
    except Exception as e:
        return [], -1, str(e)

def open_file(file_path:str, mode:str='r') -> tuple[open, int, str]:
    """Open a file with the given mode."""
    file_path = real_path(file_path)
    try:
        return open(file_path, mode), 0, ''
    except FileNotFoundError:
        return None, 10, 'File not found'
    except PermissionError:
        return None, 20, 'Permission denied'
    except Exception as e:
        return None, -1, str(e)

def create_directory(directory:str, exist_ok:bool=False) -> tuple[bool, int, str]:
    """Create a directory with the given name."""
    directory = real_path(directory)
    try:
        os.makedirs(directory, exist_ok=exist_ok)
        return True, 0, ''
    except FileExistsError:
        return False, 10, 'Directory already exists'
    except PermissionError:
        return False, 20, 'Permission denied'
    except Exception as e:
        return False, -1, str(e)
    
def create_file(file_path:str, exist_ok:bool=False) -> tuple[bool, int, str]:
    """Create a file with the given path."""
    file_path = real_path(file_path)
    try:
        with open(file_path, 'w' if exist_ok else 'x'):
            pass
        return True, 0, ''
    except FileExistsError:
        return False, 10, 'File already exists'
    except PermissionError:
        return False, 20, 'Permission denied'
    except Exception as e:
        return False, -1, str(e)
    
def copy_file(src_path:str, dst_path:str, overwrite:bool=False) -> tuple[bool, int, str]:
    """Copy a file from the source path to the destination path."""
    src_path = real_path(src_path)
    dst_path = real_path(dst_path)
    try:
        if os.path.isfile(dst_path) and not overwrite:
            return False, 10, 'File already exists'
        shutil.copyfile(src_path, dst_path, follow_symlinks=False)
        return True, 0, ''
    except FileNotFoundError:
        return False, 11, 'Source file not found'
    except IsADirectoryError:
        return False, 12, 'Destination is a directory'
    except PermissionError:
        return False, 20, 'Permission denied'
    except Exception as e:
        return False, -1, str(e)

def delete_directory(directory:str, recursive:bool=False) -> tuple[bool, int, str]:
    """Delete a directory with the given name."""
    directory = real_path(directory)
    try:
        if recursive:
            shutil.rmtree(directory)
        else:
            os.rmdir(directory)
        return True, 0, ''
    except OSError:
        return False, 10, 'Directory not empty'
    except PermissionError:
        return False, 20, 'Permission denied'
    except Exception as e:
        return False, -1, str(e)

def delete_file(file_path:str) -> tuple[bool, int, str]:
    """Delete a file with the given path."""
    file_path = real_path(file_path)
    try:
        os.remove(file_path)
        return True, 0, ''
    except FileNotFoundError:
        return False, 10, 'File not found'
    except PermissionError:
        return False, 20, 'Permission denied'
    except Exception as e:
        return False, -1, str(e)
    
def move_file(src_path:str, dst_path:str, overwrite:bool=False) -> tuple[bool, int, str]:
    """Move a file from the source path to the destination path."""
    src_path = real_path(src_path)
    dst_path = real_path(dst_path)
    try:
        if os.path.isfile(dst_path) and not overwrite:
            return False, 10, 'File already exists'
        shutil.move(src_path, dst_path)
        return True, 0, ''
    except FileNotFoundError:
        return False, 11, 'Source file not found'
    except IsADirectoryError:
        return False, 12, 'Destination is a directory'
    except PermissionError:
        return False, 20, 'Permission denied'
    except Exception as e:
        return False, -1, str(e)
    
def move_directory(src_path:str, dst_path:str, overwrite:bool=False) -> tuple[bool, int, str]:
    """Move a directory from the source path to the destination path."""
    src_path = real_path(src_path)
    dst_path = real_path(dst_path)
    try:
        if os.path.isdir(dst_path) and not overwrite:
            return False, 10, 'Directory already exists'
        shutil.move(src_path, dst_path)
        return True, 0, ''
    except FileNotFoundError:
        return False, 11, 'Source directory not found'
    except IsADirectoryError:
        return False, 12, 'Destination is a file'
    except PermissionError:
        return False, 20, 'Permission denied'
    except Exception as e:
        return False, -1, str(e)